using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class FunLib
{
    public static void UIDubug(string str)
    {
        GameObject obj = GameObject.FindGameObjectWithTag("Debug");
        if(obj)
        {
            Text text = obj.GetComponent<Text>();
            if(text)
            {
                text.text = str;
            }
        }
    }

    public static int GetIntInString(string str)
    {
        string num = System.Text.RegularExpressions.Regex.Replace(str, @"[^0-9]+", "");
        return int.Parse(num);
    }

    public static void DebugCircle(Vector3 center, float r, int step, Color color)
    {
        Vector3[] points = new Vector3[360 / step + 1];

        for (int i = 0; i <= 360; i += step)
        {
            float angle = i / 180f * Mathf.PI;
            float x = r * Mathf.Sin(angle);
            float y = r * Mathf.Cos(angle);
            points[i/step] = new Vector3(center.x + x, center.y + y, 0);
        }

        for (int i = 0; i < points.Length-1; i++)
        {
            Debug.DrawLine(points[i], points[i + 1], color);
        }
    }

    public static void ShowCircle(LineRenderer line, Vector3 center, float r, int step)
    {
        line.positionCount = 360 / step + 1;
        for (int i = 0; i <= 360; i += step)
        {
            float angle = i / 180f * Mathf.PI;
            float x = r * Mathf.Sin(angle);
            float y = r * Mathf.Cos(angle);
            line.SetPosition(i / step, new Vector3(center.x + x, center.y + y, 0));
        }
    }

    public static bool IsClickUI()
    {
        PointerEventData eventData = new PointerEventData(EventSystem.current);
        eventData.pressPosition = Input.mousePosition;
        eventData.position = Input.mousePosition;

        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, results);

        return results.Count > 0;
    }

    public static float ReMap(float val, float a1, float a2, float b1 = 0, float b2 = 1)
    {
        float re = (val - a1) / (a2 - a1) * (b2 - b1) + b1;
        if(re>Mathf.Max(b1, b2))
        {
            return Mathf.Max(b1, b2);
        }
        if(re< Mathf.Min(b1, b2))
        {
            return Mathf.Min(b1, b2);
        }
        return re;
    }

    public static bool Happen(float p)
    {
        float a = Random.Range(0, 1f);
        if (a < p) return true;
        else return false;
    }

    public static float ToTarget(float a, float b, float speed)
    {
        float re;
        float temp = Mathf.Sign(b - a) * Time.deltaTime * speed;

        if (Mathf.Abs(a - b) <= Mathf.Abs(temp))
        {
            re = b;
        }
        else
        {
            re = a + temp;
        }
        return re;
    }

    public static GameObject FindGameObjectInChildern(Transform transform, string targetName)
    {
        if (transform == null) return null;
        if (targetName.Length == 0) return null;

        Transform re = transform.Find(targetName);

        if(re==null)
        {
            if (transform.childCount == 0) return null;
            else
            {
                for(int i=0; i< transform.childCount; i++)
                {
                    GameObject obj = FindGameObjectInChildern(transform.GetChild(i), targetName);
                    if (obj != null) return obj;
                }
                return null;
            }
        }
        else
        {
            return re.gameObject;
        }
    }

    public static float ParabolicDistance(float angle, float v0, float g, float k, float h)
    {
        g = Mathf.Abs(g);
        float Vx = v0 * Mathf.Cos(angle);
        float Vy = v0 * Mathf.Sin(angle);

        if(angle>=0)
        {
            float t = -1 / k * Mathf.Log(g / (g + k * Vy));
            float y1 = -g * t / k + (Vy + g / k) / k * (1 - Mathf.Exp(-k * t));

            t += ParabolicTime(g, k, y1+h);

            float xx = Vx / k * (1 - Mathf.Exp(-k * t));
            return xx;
        }
        else
        {
            float t = ParabolicTime(g, k, h, Vy);
            float xx = Vx / k * (1 - Mathf.Exp(-k * t));
            return xx;
        }
    }

    public static float ParabolicTime(float g, float k, float y1)
    {
        float y2 = 0;
        float t = 0;
        for (; y2 < y1; t += 0.1f)
        {
            y2 = g / k / k * (Mathf.Exp(-k * t) + k * t - 1);
        }
        return t;
    }

    public static float ParabolicAngle(float v0, float s1, float g, float k, float h)
    {
        float ofst = s1;
        float re = 0;
        for (int angle = 89; angle > 0; angle--)
        {
            float a = angle / 180.0f * Mathf.PI;

            float s2 = ParabolicDistance(a, v0, g, k, h);

            if (Mathf.Abs(s2 - s1) < ofst)
            {
                ofst = Mathf.Abs(s2 - s1);
                re = a;
            }
            else
            {
                return a;
            }
        }
        return re;
    }

    public static float ParabolicSpeed(float angle, float s1, float g, float k, float h)
    {
        float ofst = s1;
        float re = 0;
        for (float speed = 10; speed <= 40; speed +=0.5f)
        {
            float s2 = ParabolicDistance(angle, speed, g, k, h);

            if (Mathf.Abs(s2 - s1) < ofst)
            {
                ofst = Mathf.Abs(s2 - s1);
                re = speed;
            }
            else
            {
                return speed;
            }
        }
        return re;
    }

    static float ParabolicTime(float g, float k, float y1, float vy)
    {

        for (float t = 0; t < 10; t += Time.deltaTime)
        {
            float y2 = g / k / k * (Mathf.Exp(-k * t) + k * t - 1) + vy / k * Mathf.Exp(-k * t - 1);

            if (Mathf.Abs(y1 - y2) < 0.5f) return t;
        }
        return 10;
    }
}
